import time
import os

from django.db import transaction
from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
from fdfs_client.client import get_tracker_conf, Fdfs_client
import logging

from rest_framework import status
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin, CreateModelMixin
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_500_INTERNAL_SERVER_ERROR
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet

from DRFStudy_34.settings import alipay
from shopping.models import Classification, Commodity, CommodityImg, ShoppingCart, Order, Payment
from shopping.serializers import ClassificationSerializer, ParentClassificationSerializer, CommoditySerializer, \
    ShoppingCartSerializer, OrderSerializer, PaymentSerializer
from celery_tasks.email.tasks import send_mail_task

from celery_tasks.order.tasks import cancel_expired_orders_task
from celery_tasks.sms.tasks import send_order_sms_task


class ClassificationViewSet(GenericViewSet, ListModelMixin):
    queryset = Classification.objects.filter(is_delete=False)
    serializer_class = ClassificationSerializer
    permission_classes = [IsAuthenticated]

    # 重写查询集
    def get_queryset(self):
        if self.action == 'list':
            return self.queryset.filter(parent__isnull=True)
        else:
            return self.queryset

    # 重写序列化器
    def get_serializer_class(self):
        if self.action == 'list':
            return ParentClassificationSerializer
        else:
            return self.serializer_class

    @action(methods=['get'], detail=True, url_path='commodity')
    def commodity_list(self, request, pk):
        """
        商品列表接口
        """
        # 获取一级分类下的所有商品 服饰 短袖 长袖 长裤 ...

        # 获取二级分类下的所有商品 服饰下面的短袖商品 长袖商品 ...
        try:
            classification = self.get_queryset().get(id=pk)
        except Classification.DoesNotExist:
            return Response({"message": "分类不存在"}, status=status.HTTP_404_NOT_FOUND)
        # 通过分类得到对应的商品
        # classifications1 应该是一个变量 可以是一级也可以是二级
        # 默认查询一级分类下的所有商品
        classification_attr = 'classification1'
        # 获取分类名称
        classification_name = classification.name
        # 判断是一级分类还是二级分类
        if classification.parent:
            classification_attr = 'classification2'
            # 二级分类名要做拼接的操作 得到父级分类的名字拼接二级分类名
            # 拼接分类名 服饰+服饰
            classification_name = f'{classification.parent.name}--{classification.name}'
        # classification_attr 保存的是商品分类的管理器名称
        # classification_attr 当做模型的属性  getattr 获取对象的属性值
        # 获取分类下的所有商品
        data = getattr(classification, classification_attr).filter(is_delete=False, status=1)
        return Response({"classification": classification_name, "commodity": CommoditySerializer(data, many=True).data})


# 导入日志器
logger = logging.getLogger(__name__)
tracker_path = get_tracker_conf('utils/fastdfs/client.conf')
client = Fdfs_client(tracker_path)


class CommodityViewSet(ModelViewSet):
    queryset = Commodity.objects.filter(status=1, is_delete=False)
    serializer_class = CommoditySerializer
    permission_classes = [IsAuthenticated]

    # 重写create方法
    from django.db import transaction

    # 正确的位置应该是在 shopping/views.py 的 CommodityViewSet.create 方法中
    @transaction.atomic
    def create(self, request, *args, **kwargs):
        # 获取用户传入的数据
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        # 验证分类字段是否为空
        if not serializer.validated_data.get('classification1'):
            return Response({"message": "请填写一级分类"}, status=status.HTTP_400_BAD_REQUEST)

        if not serializer.validated_data.get('classification2'):
            return Response({"message": "请填写二级分类"}, status=status.HTTP_400_BAD_REQUEST)

        # 保存商品数据
        commodity = serializer.save()

        # 保存商品图片数据
        files = request.FILES.getlist("file")
        image_records = []

        try:
            # 遍历图片数据
            for file in files:
                # 验证文件类型
                if file.content_type not in ["image/jpeg", "image/png"]:
                    return Response({"message": "上传的图片格式不符合要求"}, status=status.HTTP_400_BAD_REQUEST)

                # 验证文件大小
                if file.size > 5 * 1024 * 1024:  # 5MB限制
                    return Response({"message": "上传的图片过大"}, status=status.HTTP_400_BAD_REQUEST)

                # 处理文件名 - 更安全的实现
                try:
                    original_name = file.name

                    # 如果文件名为空，则使用默认名称
                    if not original_name or original_name.strip(".")[-1] == "":
                        # 使用时间戳生成唯一文件名
                        timestamp = int(time.time())
                        file.name = f"image_{timestamp}.jpg"
                    else:
                        # 提取文件名和扩展名
                        name, ext = os.path.splitext(original_name)

                        # 如果没有扩展名，则根据内容类型添加
                        if not ext.lower() in [".jpg", ".jpeg", ".png"]:
                            if file.content_type == "image/jpeg":
                                file.name = name + ".jpg"
                            elif file.content_type == "image/png":
                                file.name = name + ".png"
                            else:
                                file.name = name + ".jpg"
                        else:
                            # 如果已经有扩展名，但不是有效的图片格式，需要转换
                            if ext.lower() not in [".jpg", ".jpeg", ".png"]:
                                if file.content_type == "image/jpeg":
                                    file.name = name + ".jpg"
                                elif file.content_type == "image/png":
                                    file.name = name + ".png"
                                else:
                                    file.name = name + ".jpg"
                except Exception as e:
                    logger.error(f"上传图片时文件名处理异常: {e}")
                    return Response({"message": "上传的图片文件名处理失败"}, status=status.HTTP_400_BAD_REQUEST)

                try:
                    upload_result = client.upload_by_buffer(file.read(), file.name)
                    # 增加对上传结果的详细检查
                    if upload_result.get("Status") != "Upload successed.":
                        # 记录详细错误信息
                        logger.error(f"图片上传失败: {upload_result}")
                        return Response({"message": "上传图片失败"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                except Exception as e:
                    logger.error("图片上传失败：%s" % e)
                    return Response({"message": "上传图片失败"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                images_name = upload_result.get("Remote file_id").decode()
                image_records.append(images_name)

            # 保存商品图片数据
            for image_src in image_records:
                CommodityImg.objects.create(src=image_src, commodity=commodity)

            return Response(serializer.data, status=status.HTTP_201_CREATED)

        except Exception as e:
            logger.error("商品创建过程中发生错误：%s" % str(e))
            return Response({"message": "商品创建失败"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(methods=["get"], detail=False)
    def optimization(self, request):
        """
        优选商品接口
        优先按销量排序，其次按评价数排序，最后按创建时间排序
        """
        queryset = self.get_queryset().order_by("-sales", "-comments", "-create_time")[:10]
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    # 限制只能查看已经发布的商品
    def get_queryset(self):
        if self.action in ["list", "retrieve"]:
            return self.queryset.filter(status=1)
        else:
            return self.queryset


# 购物车视图集
class ShoppingCartViewSet(ModelViewSet):
    queryset = ShoppingCart.objects.all()
    serializer_class = ShoppingCartSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        # 限制登录用户只能查看自己的购物车
        return self.request.user.shoppingcart_set.all()

    # 重写create创建方法 限制登录用户只能添加自己的商品到购物车
    def create(self, request, *args, **kwargs):
        request.POST._mutable = True
        request.data['user'] = request.user.id
        return ModelViewSet.create(self, request, *args, **kwargs)

    # 重写update修改方法 登录用户只能修改自己的购物车
    def update(self, request, *args, **kwargs):
        request.POST._mutable = True
        request.data['user'] = request.user.id
        return ModelViewSet.update(self, request, *args, **kwargs)


# 订单视图集 只读和创建的操作 不能修改和删除
class OrderViewSet(ReadOnlyModelViewSet, CreateModelMixin):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer
    permission_classes = [IsAuthenticated]

    # 限制登录用户只能查看自己的订单
    def get_queryset(self):
        return self.request.user.order_set.all()

    # 修正订单状态更新接口
    @action(methods=["put"], detail=False)
    def status(self, request, send_email_task=None):
        query_dict = request.query_params
        data = query_dict.dict()

        # 得到订单编号
        order_id = data.get("out_trade_no")
        # 支付宝交易号
        trade_no = data.get("trade_no")

        # 参数验证
        if not order_id or not trade_no:
            return Response({"message": "缺少必要的参数"}, status=status.HTTP_400_BAD_REQUEST)

        # 开启事务
        with transaction.atomic():
            # 创建保存点
            save_point = transaction.savepoint()
            try:
                # 先验证订单是否存在
                try:
                    order = self.get_queryset().get(order_id=order_id)
                except Order.DoesNotExist:
                    raise Exception("订单不存在")

                # 检查订单当前状态
                if order.status == 2:
                    # 订单已经是支付状态，可能是重复回调
                    logger.info(f"订单 {order_id} 已经是支付状态，支付宝回调可能是重复通知")
                    transaction.savepoint_rollback(save_point)  # 回滚保存点，避免重复创建支付记录
                    return Response({
                        "order_id": order_id,
                        "trade_id": trade_no,
                        "message": "订单已经是支付状态"
                    }, status=status.HTTP_200_OK)
                elif order.status not in [0, 1]:
                    # 订单状态不正确（不是待支付状态）
                    raise Exception("订单状态不正确，无法进行支付")

                # 创建支付记录
                Payment.objects.create(
                    order=order,
                    trade_id=trade_no
                )

                # 更新订单状态为已支付（状态2）
                order.status = 2
                order.save()

            except Exception as e:
                logger.error("订单支付失败：%s" % str(e))
                transaction.savepoint_rollback(save_point)
                return Response({"message": f"订单支付失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            else:
                transaction.savepoint_commit(save_point)
                # 邮件通知 先获取所有的商品信息
                for i in self.get_queryset().get(order_id=order_id).ordergoods_set.all():
                    # 得到订单中的每个商品信息 用于写入邮件里面
                    send_mail_task.delay(i.order.user.email,
                                         f"""
                                          <h2>订单支付成功</h2>
                                          <h3>商品名称：{i.commodity.name}*{i.number}待发货</h3>
                    
                    """)

            return Response({
                "order_id": order_id,
                "trade_id": trade_no,
                "message": "订单支付成功"
            }, status=status.HTTP_200_OK)


# 支付视图集
class PaymentViewSet(ReadOnlyModelViewSet):
    queryset = Payment.objects.all()
    serializer_class = PaymentSerializer

    @action(methods=["get"], detail=True)
    def pay(self, request, pk):
        """
        得到支付宝的支付页面 返回给客户端让用户支付
        :param request:
        :param pk: 这里应该是订单ID，不是支付ID
        :return:
        """
        try:
            # 注意：这里应该查找订单而不是支付
            order = Order.objects.get(order_id=pk, user=request.user)
            # 检查订单状态，只有待支付的订单才能支付
            if order.status != 0 and order.status != 1:
                return Response({"message": "订单状态不正确"}, status=status.HTTP_400_BAD_REQUEST)
        except Order.DoesNotExist:
            return Response({"message": "订单不存在"}, status=status.HTTP_404_NOT_FOUND)

        # 调用支付宝接口
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order.order_id,
            total_amount=str(order.total_amount),
            subject=f'XIAO_BEI订单支付{order.order_id}',
            # 修改为正确的回调地址
            return_url="http://localhost:5173/order/success"  # 修正拼写错误 "succss" -> "success"
        )
        # 生成支付页面
        pay_url = "https://openapi-sandbox.dl.alipaydev.com/gateway.do?" + order_string
        return Response({"pay_url": pay_url}, status=status.HTTP_200_OK)

    # 在订单相关视图中
    # 订单支付回调处理
    def handle_payment_callback(request, process_order_payment_task=None):
        order_id = request.data.get('out_trade_no')
        trade_no = request.data.get('trade_no')

        # 处理订单支付
        payment_data = {
            'trade_no': trade_no,
            'payment_method': 'alipay',
            'amount': request.data.get('total_amount')
        }

        # 异步处理订单支付
        process_order_payment_task.delay(order_id, payment_data)

        # 发送订单通知短信
        order = Order.objects.get(order_id=order_id)
        send_order_sms_task.delay(
            order.user.mobile,
            f"您的订单{order_id}已支付成功，金额：{order.total_amount}元"
        )

        return Response({'message': '支付处理成功'})
